﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;

namespace Draco.OWF.Studio.Common.Geometry
{
    public enum LineSegRelation
    {
        Disjoint, Overlap, Intersection
    }
    /// <summary>
    /// LineSeg
    /// </summary>
    public class LineSeg 
    {
        public GeoLine Line { get; private set; }
        public Point Start { get; private set; }
        public Point End { get; private set; }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        public LineSeg(Point a, Point b) 
        {
            this.Start = a;
            this.End = b;
            Line = new GeoLine(a, b);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="p"></param>
        /// <returns></returns>
        public bool IsPointOnLineSeg(Point p)
        {
            if (Line.IsPointOnLine(p))
            {
                return p.X >= Math.Min(this.Start.X, this.End.X) && p.X <= Math.Max(this.Start.X, this.End.X) &&
                    p.Y >= Math.Min(this.Start.Y, this.End.Y) && p.Y <= Math.Max(this.Start.Y, this.End.Y);
            }
            return false;
        }

        public LineSegRelation GetRelationWithLineSeg(LineSeg lineSeg)
        {
            LinesRelation relation = this.Line.GetRelationWithLine(lineSeg.Line);
            if (relation == LinesRelation.Parallel)
                return LineSegRelation.Disjoint;
            if (relation == LinesRelation.Overlap)
            {
                if ((this.Start.X >= Math.Min(lineSeg.Start.X, lineSeg.End.X) &&
                    this.Start.X <= Math.Max(lineSeg.Start.X, lineSeg.End.X)) ||
                    (this.End.X >= Math.Min(lineSeg.Start.X, lineSeg.End.X) &&
                    this.End.X <= Math.Max(lineSeg.Start.X, lineSeg.End.X)))
                    return LineSegRelation.Overlap;
                else
                    return LineSegRelation.Disjoint;
            }
            if (relation == LinesRelation.Intersection)
            {
                Point? p = this.Line.GetIntersectionPoint(lineSeg.Line);
                if (!IsPointOnLineSeg(p.Value))
                    return LineSegRelation.Disjoint;
                else
                    return LineSegRelation.Intersection;
            }
            return LineSegRelation.Disjoint;
        }

        public Point? GetIntersectionPoint(LineSeg lineSeg)
        {
            Point? p = this.Line.GetIntersectionPoint(lineSeg.Line);
            if (p.HasValue)
            {
                if (IsPointOnLineSeg(p.Value))
                    return p.Value;
            }
            return null;
        }
    }
}
